package service

import (
	"errors"
	"fmt"
	"gitee.com/sansaniot/ssiot-core/facade/env"
	"gitee.com/sansaniot/ssiot-core/httpmvc/service"
	log "gitee.com/sansaniot/ssiot-core/logger"
	huge "github.com/dablelv/go-huge-util"
	"gorm.io/gorm"
	"ssadmin/common/constant"
	cDto "ssadmin/common/query"
	"ssadmin/common/utils"
	"ssadmin/internal/admin/models"
	"ssadmin/internal/admin/models/command"
	"ssadmin/internal/admin/models/query"
	cache "ssadmin/internal/admin/utils"
	"strings"
	"time"
)

type Dept struct {
	service.Service
}

// GetList  获取Dept列表
func (e *Dept) GetList(c *query.DeptQuery, res *[]map[string]interface{}) error {
	return DeptList(e.Orm, c, res)
}

func DeptList(db *gorm.DB, c *query.DeptQuery, res *[]map[string]interface{}) error {
	//获取用户分组
	if len(c.UserId) > 0 && c.UserId != constant.AdminUser {
		c.DeptIdList = cache.GetUserDeptIds(c.UserName)
	}

	start := time.Now()
	//获取分组列表
	deptList := make([]models.Dept, 0)
	where := cDto.MakeCondition(c.GetNeedSearch())
	if c.PageIndex > 0 && c.PageSize > 0 {
		if err := (models.Dept{}).FindList(db, &deptList, where, cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), cDto.OrderDest("create_time", true)); err != nil {
			return err
		}
	} else {
		if err := (models.Dept{}).FindList(db, &deptList, where, cDto.OrderDest("create_time", true)); err != nil {
			return err
		}
	}
	end := time.Now()
	log.Infof("query dept, dept list time=%d, size=%d", end.Unix()-start.Unix(), len(deptList))

	start = time.Now()
	for _, info := range deptList {
		info.CreateTime = info.CreateTimeDts.Format(utils.TIME_FMT_FULL)
		info.ModifyTime = info.ModifyTimeDts.Format(utils.TIME_FMT_FULL)

		if strings.Contains(info.CreateTime, utils.TIME_NIL) {
			info.CreateTime = ""
		}

		if strings.Contains(info.ModifyTime, utils.TIME_NIL) {
			info.ModifyTime = ""
		}

		if info.Type == "" {
			info.Type = constant.NodeTypeDept
		}

		m := make(map[string]interface{})
		utils.ConvtStructToMap(info, m)
		m["key"] = fmt.Sprintf("%s_%s", constant.NodeTypeDept, info.DeptId)
		*res = append(*res, m)
	}
	end = time.Now()
	log.Infof("query dept, dept convert time=%d, size=%d", end.Unix()-start.Unix(), len(*res))
	return nil
}

// GetDetail 获取Dept对象
func (e *Dept) GetDetail(c *query.DeptQuery, res map[string]interface{}) error {
	param, err := c.GetId()
	if err != nil {
		return err
	}

	if c.Type == constant.NodeTypeDept {

	} else {
		//分组信息
		dept := models.Dept{}
		where := cDto.MakeCondition(param)
		err = dept.FindOne(e.Orm, &dept, where)
		dept.CreateTime = dept.CreateTimeDts.Format(utils.TIME_FMT_FULL)
		dept.ModifyTime = dept.ModifyTimeDts.Format(utils.TIME_FMT_FULL)
		utils.ConvtStructToMap(dept, res)
	}

	return err
}

// Insert 创建Dept对象
func (e *Dept) Insert(c *command.DeptInsertReq) error {
	deptModel := models.Dept{}
	c.Generate(&deptModel)

	//admin创建的分组为租户分组
	//if c.CreatorId == constant.AdminUser && (deptModel.ParentId == "0" || len(deptModel.ParentId) == 0) {
	//deptModel.Type = constant.NodeTypeDept

	txErr := e.Orm.Transaction(func(tx *gorm.DB) error {
		//添加分组
		if err := deptModel.Add(tx, &deptModel); err != nil {
			return err
		}

		userDeptList := []models.UserDept{}
		userDeptList = append(userDeptList, models.UserDept{
			UserId: c.CreatorId,
			DeptId: deptModel.DeptId,
		})

		userMap := map[string]string{}
		userMap[c.CreatorId] = c.CreatorId

		//循环获取上级用户
		tu := models.User{UserId: c.CreatorId, CreatorId: c.UpperCreatorId}
		for len(tu.CreatorId) > 0 {
			//已经存在用户，退出，比较死循环  这样最多向上寻找两级就退出了，去掉
			//if _, exixt := userMap[tu.CreatorId]; exixt {
			//	break
			//}
			//添加上级用户分组
			userMap[tu.CreatorId] = tu.CreatorId
			userDeptList = append(userDeptList, models.UserDept{
				UserId: tu.CreatorId,
				DeptId: deptModel.DeptId,
			})

			//继续查询上级用户
			tu = models.User{UserId: tu.CreatorId}
			if err := tu.FindOne(e.Orm, &tu); err != nil {
				return err
			}
			if tu.Creator == "admin" {
				break
			}
		}

		//添加用户分组
		ud := models.UserDept{}
		if err := ud.Add(tx, &userDeptList); err != nil {
			return err
		}

		//获取登录用户分组缓存
		deptIds := cache.GetUserDeptIds(c.Creator)

		//更新登录用户分组缓存
		deptIds = append(deptIds, deptModel.DeptId)
		deptIds = huge.UniqueStrSlice(deptIds)
		key := fmt.Sprintf("login_user:%s", c.Creator)
		deptField := make(map[string]interface{})
		deptField[constant.CacheKeyUserDeptIds] = strings.Join(deptIds, ",")
		if err := env.Cache.HashSet(key, deptField); err != nil {
			return err
		}
		return nil
	})

	return txErr
}

// Update 修改Dept对象
func (e *Dept) Update(c *command.DeptUpdateReq) error {
	if utils.IsReservedDept(c.DeptId) && c.CreatorId != constant.AdminUser {
		return errors.New("无法修改系统保留分组")
	}

	//修改机构
	var data = models.Dept{}
	id := query.DeptQuery{DeptId: c.DeptId}
	where := cDto.MakeCondition(id)
	if err := data.FindOne(e.Orm, &data, where); err != nil {
		return err
	}

	if len(data.DeptId) == 0 {
		return errors.New("no record")
	}

	c.Generate(&data)

	return e.Orm.Transaction(func(tx *gorm.DB) error {
		if err := data.Mod(tx, &data, where); err != nil {
			return err
		}
		return nil
	})
}

// Remove 删除Dept
func (e *Dept) Remove(c *command.DeptDeleteReq) error {
	var data = models.Dept{}
	deptIdList := c.GetId()

	if len(deptIdList) > 0 {
		var childCount int64 = 0
		_ = data.FindCountByConds(e.Orm, &childCount, "parent_id in (?)", deptIdList)

		if childCount > 0 {
			return errors.New("当前分组有子分组，无法删除")
		}

		for _, deptId := range deptIdList {
			if utils.IsReservedDept(deptId) && c.CreatorId != constant.AdminUser {
				return errors.New("选择的分组中包含系统保留分组，请重新选择")
			}
		}
	}

	conds := "id in (?)"
	txErr := e.Orm.Transaction(func(tx *gorm.DB) error {
		var err error
		//删除分组
		if len(deptIdList) > 0 {
			err = data.Del(tx, conds, deptIdList)
			if err != nil {
				return err
			}
			ud := models.UserDept{}
			err = ud.Del(tx, &ud, "dept_id in (?)", deptIdList)
			if err != nil {
				return err
			}
		}

		return nil
	})

	return txErr
}
